﻿using System;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;

namespace RunAllTestsInSolutionTask
{
    public class RunAllTestsInSolution : Task
    {
        [Required]
        public string MSTest
        {
            get;
            set;
        }

        [Required]
        public string SolutionFile
        {
            get;
            set;
        }

        public string Parmaters
        {
            get;
            set;
        }

        public string Configuration
        {
            get;
            set;
        }

        public string ExcludeProject { get; set; }

        public override bool Execute()
        {
            try
            {
                if (string.IsNullOrEmpty(Configuration))
                    Configuration = "Debug";
                IList<string> dlls = null;
                if (string.IsNullOrEmpty(ExcludeProject))
                    dlls = SolutionParser.GetAllTestDlls(SolutionFile, Configuration);
                else
                    dlls = SolutionParser.GetAllTestDlls(SolutionFile, Configuration, ExcludeProject);

                ProcessStartInfo info = CreateProcessStartInfo(dlls);
                Console.WriteLine("executing Tests:");
                Console.WriteLine(info.FileName + " " + info.Arguments);

                Process testRunnerProc = new Process();
                testRunnerProc.StartInfo = info;
                testRunnerProc.StartInfo.UseShellExecute = false;
                testRunnerProc.StartInfo.RedirectStandardOutput = true;

                testRunnerProc.OutputDataReceived += new DataReceivedEventHandler(this.PrintToConsole);
                testRunnerProc.Start();
                System.Threading.Thread.Sleep(1000);
                testRunnerProc.BeginOutputReadLine();
                testRunnerProc.WaitForExit();

                return 0 == testRunnerProc.ExitCode;
            }
            catch (Win32Exception)
            {
                Console.WriteLine("Couldn't locate MSTest.exe. Check that path to mstest is correct");
                Console.WriteLine("If using MStestLocation as variable remove \" from the location dir");
                throw;
            }

        }

        private void PrintToConsole(object sendingProcess,
            DataReceivedEventArgs outLine)
        {
            if (string.IsNullOrEmpty(outLine.Data))
                return;
            if (this.BuildEngine != null)
            {

                this.Log.LogMessage(outLine.Data);
            }
            else
            {
                Console.WriteLine(outLine.Data);
            }
        }

        virtual protected ProcessStartInfo CreateProcessStartInfo(IList<string> testdlls)
        {
            var processInfo = new ProcessStartInfo();
            processInfo.FileName = MSTest;
            foreach (var dll in testdlls)
            {
                processInfo.Arguments += @"/TestContainer:" + "\"" + dll + "\" ";
            }
            processInfo.Arguments += this.Parmaters;
            return processInfo;
        }
    }
}
